// Generator

function * foo () {
  console.log('1111')
  yield 100
  console.log('2222')
  yield 200
  console.log('3333')
  yield 300
}

// 调用Generator函数后，该函数并不执行，返回一个遍历器对象Iterator
const generator = foo()

// 调用遍历器对象的next方法执行Generator函数，遇到yield后暂停
// next返回一个对象，value属性是当前yield语句的值，done属性表示遍历是否结束

console.log(generator.next()) // { value: 100, done: false }
console.log(generator.next()) // { value: 200, done: false }
console.log(generator.next()) // { value: 300, done: false }
console.log(generator.next()) // { value: undefined, done: true }

// Generator应用------------------------------------
// 实现发号器
function * createIdMaker () {
  let id = 1
  while (true) {
    yield id++
  }
}

const idMaker = createIdMaker()

console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)

// 实现对象的iterator 方法
const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '外语'],
  work: ['喝茶'],
  [Symbol.iterator]: function * () {
    const all = [...this.life, ...this.learn, ...this.work]
    for (const item of all) {
      yield item
    }
  }
}

for (const item of todos) {
  console.log(item)
}

// 实现斐波那契数列
function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  if (n > 100) break;
  console.log(n);
}

// yield*语句-----------------------------------
// yield*语句，可以用来在一个Generator函数里面执行另一个Generator函数

function* foo2() {
  yield 'a';
  yield 'b';
}

function* bar2() {
  yield 'x';
  yield* foo2();
  yield 'y';
}

for (let n of bar2()) {
  console.log(n); // x a b y
}

// 如果yield命令后面跟的是一个遍历器对象，需要在yield命令后面加上星号，表明它返回的是一个遍历器对象
// function* gen(){
//   yield ["a", "b", "c"];
// }

// for (let n of gen()) {
//   console.log(n); //  ["a", "b", "c"]
// }

function* gen(){
  yield* ["a", "b", "c"];
}

for (let n of gen()) {
  console.log(n); // a b c
}
